<?php

namespace App\Http\Controllers\VideoAdmin;

use App\Http\Config\ErrorCode;
use App\Library\Tools;
use App\Models\video\VideoSettingModel;
use Illuminate\Http\Request;
use App\Http\Controllers\Admin\BaseController;
use Illuminate\Support\Facades\DB;

class WxMiniProgramController extends BaseController
{
    private $wxMiniCheckUpdateUrl = "https://update.netbcloud.com/public/index.php/wxApp/";
    private $invokeCodeUrl = "http://111.230.236.45/api/project/getInvokeCode"; // window 发布机
    private $windowPublicUrl = "http://111.230.236.45/api/project/upload"; // window 发布机
    private $windowLoginUrl = "http://111.230.236.45/api/project/login"; // window 发布机
    private $windowPreviewUrl = "http://111.230.236.45/api/project/preview"; // window 发布机
    private $windowPublishUrl = "http://111.230.236.45/api/project/publish"; // window 发布机
    private $wxMiniProjectName = "可美TV";
    public function __construct(Request $request){
        parent::__construct($request);
    }

    // 检查更新
    public function index(Request $request){
        if ($this->returnData['code'] > 0){
            return $this->returnData;
        }
        $data = DB::table('up_wxapp_upgrade')->orderBy('create_time','desc')->where("mall_id", $request->mallData["id"])->select('version')->first();
        $version = !empty($data->version) ? $data->version : "0";
        $result = Tools::curl($this->wxMiniCheckUpdateUrl."checkVersion", json_encode(["version" => $version, "projectName" => $this->wxMiniProjectName]));
        if(substr($result, 0,2) == "{\""){
            $result = json_decode($result, true);
        }else{
            $result = json_decode(substr($result, 3), true);
        }
        if(isset($result["code"]))
            return $this->return_result($result);
        else{
            return $this->return_result(ErrorCode::$admin_enum['fail']);
        }
    }

    public function handleMiniContent($fileUrl, $version){
        $dir = sys_get_temp_dir();
        if(!is_dir($dir. "/miniPackage")) {
            mkdir($dir . "/miniPackage");
        }
        $content = json_decode(@file_get_contents($fileUrl."/project.config.json"), true);
        if(!$content){
            return false;
        }
        $data = VideoSettingModel::getFields("app_id", ["mall_id" => request()->mallData["id"]], true, false);;
        $content["appid"] = !empty($data["appId"]) ? $data["appId"] : '';
        file_put_contents($dir."/miniPackage/project.config.json", json_encode($content, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT));
        file_put_contents($dir."/miniPackage/config.js", @file_get_contents($fileUrl."/config.js"));
        $arr = file($dir."/miniPackage/config.js");
//        global $scf_data;
//        if (isset($scf_data["IS_SCF"]) && $scf_data["IS_SCF"] == true){
//            $url = $scf_data['host'];
//        }else{
//            $url = $_SERVER["REQUEST_SCHEME"] . '://'.$_SERVER['HTTP_HOST'];
//        }
        foreach ($arr as &$item) {
            if ($i = strpos($item, "Config['SAAS_ID']") !== false) {
                $item = "Config['SAAS_ID'] = '".request()->mallData["id"]."';\n";
            }
        }
        file_put_contents($dir."/miniPackage/config.js", implode("", $arr));
        $zip = new \ZipArchive;//新建一个ZipArchive的对象
        if ($zip->open($dir. "/temp.zip", \ZipArchive::CREATE) === TRUE) {
            $this->addFileToZip($dir. "/miniPackage", $zip, $dir. "/miniPackage");
            $zip->close();//关闭处理的zip文件
        } else {
            return false;
        }
        $pathInfo = pathinfo($dir. "/temp.zip");
        $fileParam = ["name" => $pathInfo["basename"], "type" => $pathInfo["extension"], "tmp_name" => $dir. "/temp.zip"];
        $formData = $this->getFormData(["project" => $this->wxMiniProjectName, "app" => "wxApp", "version" => $version], ["file" => $fileParam]);
        $res = $this->curl($this->windowPublicUrl, $formData[0], ['Content-Type: multipart/form-data; boundary=' . $formData[1]]);
        $res = json_decode($res, 1);
        @unlink($dir. "/temp.zip");
        if($res["code"] == "0"){
            return true;
        }
        return false;
    }

    function addFileToZip($path, \ZipArchive $zip, $org)
    {
        $handler = @opendir($path); //打开当前文件夹由$path指定。
        while (($filename = @readdir($handler)) !== false) {
            if ($filename != "." && $filename != "..") {//文件夹文件名字为'.'和‘..’，不要对他们进行操作
                if (is_dir($path . "/" . $filename)) {// 如果读取的某个对象是文件夹，则递归
                    $this->addFileToZip($path . "/" . $filename, $zip, $org);
                } else { //将文件加入zip对象
                    $zip->addFile($path . "/" . $filename, $path != $org ? (substr($path, strlen($org)+1) . "/" . $filename) : $filename);
                }
            }
        }
        @closedir($handler);
    }

    // 获取调用码
    public function getInvokeCode(Request $request){
        if ($this->returnData['code'] > 0){
            return $this->returnData;
        }
        $version = $request->version;
        $formData = $this->getFormData(["project" => $this->wxMiniProjectName, "app" => "wxApp", "version" => $version]);
        $res = $this->curl($this->invokeCodeUrl, $formData[0], ['Content-Type: multipart/form-data; boundary=' . $formData[1]]);
        $res = json_decode($res, true);
        if($res["code"] == "0"){
            $result = Tools::curl($this->wxMiniCheckUpdateUrl."getFiles", json_encode(["version" => $version, "projectName" => $this->wxMiniProjectName]));
            if(substr($result, 0,2) == "{\""){
                $result = json_decode($result, true);
            }else{
                $result = json_decode(substr($result, 3), true);
            }
            if($result["code"] == "1") {
                return $this->return_result($result);
            }
            $this->handleMiniContent($result["data"], $version);
            $this->returnData["data"] = ["invokeCode" => $res["data"]["invokeCode"]];
            return $this->return_result($this->returnData);
        }
        return $this->return_result($res);
    }

    // 获取登录二维码
    public function loginByMini(Request $request){
        if(!$request->invokeCode){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "调用码参数不存在";
            return $this->return_result($this->returnData);
        }
        $requestParam["invokeCode"] = $request->invokeCode;
        if($request->mode){
            $requestParam["mode"] = $request->mode;
        }
        $formData = $this->getFormData($requestParam);
        $res = $this->curl($this->windowLoginUrl, $formData[0], ['Content-Type: multipart/form-data; boundary=' . $formData[1]]);
        $res = json_decode($res, true);
        if($res["code"] == "10000"){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "调用码过期了，请重新开始";
            return $this->return_result($this->returnData);
        }
        if($res["code"] != "0"){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = isset($res["msg"]) ? $res["msg"] : "获取登录结果失败";
        }else {
            $this->returnData["data"] = $res["data"];
        }
        return $this->return_result($this->returnData);
    }

    // 预览码
    public function previewByMini(Request $request){
        if(!$request->invokeCode){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "调用码参数不存在";
            return $this->return_result($this->returnData);
        }
        $requestParam["invokeCode"] = $request->invokeCode;
        $requestParam["compilecondition"] = json_encode(["pathName" => "pages/index/index"]);//"{\"pathName\":\"pages/agent/homepage/index/index\",\"query\":\"a3=1\"}";
        $formData = $this->getFormData($requestParam);
        $res = $this->curl($this->windowPreviewUrl, $formData[0], ['Content-Type: multipart/form-data; boundary=' . $formData[1]]);
        $res = json_decode($res, true);
        if($res["code"] == "10000"){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "调用码过期了，请重新开始";
            return $this->return_result($this->returnData);
        }
        if($res["code"] != "0"){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = isset($res["msg"]) ? $res["msg"] : "获取预览结果失败";
        }else {
            $this->returnData["data"] = $res["data"];
        }
        return $this->return_result($this->returnData);
    }

    // 发布
    public function publishByMini(Request $request){
        if(!$request->invokeCode){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "调用码参数不存在";
            return $this->return_result($this->returnData);
        }
        if(!$request->version){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "版本号参数不存在";
            return $this->return_result($this->returnData);
        }
        $desc = $request->desc ?: '';
        $formData = $this->getFormData(["invokeCode" => $request->invokeCode, "desc" => $desc]);
        $res = $this->curl($this->windowPublishUrl, $formData[0], ['Content-Type: multipart/form-data; boundary=' . $formData[1]]);
        $res = json_decode($res, true);
        if($res["code"] == "10000"){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = "调用码过期了，请重新开始";
            return $this->return_result($this->returnData);
        }
        if($res["code"] != "0"){
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = isset($res["msg"]) ? $res["msg"] : "获取上传结果失败";
        }else {
            if(!DB::table("up_wxapp_upgrade")->where("mall_id", $request->mallData["id"])->where("version", $request->version)->count()){
                DB::table('up_wxapp_upgrade')->insert(["version" => $request->version, "remarks" => $desc, "create_time" => time(), "mall_id" => $request->mallData["id"]]);
            }
            $this->returnData["data"] = $res["data"];
        }
        return $this->return_result($this->returnData);
    }

    function getFormData($param, $file = []) {
        $body = array();
        // 普通参数
        foreach ($param as $key => $value) {
            $body_part = "Content-Disposition: form-data; name=\"$key\"\r\n";
            $body_part .= "\r\n$value";
            $body[] = $body_part;
        }
        // 上传文件处理
        foreach ($file as $key => $value) {
            $body_part = "Content-Disposition: form-data; name=\"$key\"; filename=\"{$value['name']}\"\r\n";
            $body_part .= "Content-type: {$value['type']}\r\n";
            $body_part .= "\r\n".file_get_contents($value['tmp_name']);
            $body[] = $body_part;
        }
        $boundary = "----".uniqid("WebKitFormBoundary");
        // multipart-body
        $multipart_body = "--$boundary\r\n";
        // 拼接各个域
        $multipart_body .= implode("\r\n--$boundary\r\n", $body);
        // 最后一个不同的 boundary
        $multipart_body .= "\r\n--$boundary--";
        return [$multipart_body, $boundary];
    }

    public function curl($url, $data = "", $header = ['Content-Type: application/json'], $timeout = 60)
    {
        $ch = curl_init($url);
        if(empty($data)){
            curl_setopt($ch, CURLOPT_HTTPGET, 1);
        }else {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
        if(!empty($header)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        $output = curl_exec($ch);
        $errno = curl_errno($ch);
        if ($errno) {
            curl_close($ch);
            return false;
        }
        curl_close($ch);
        return $output;
    }
}